Multimédia TP1 - Compressão de Imagem¶

David Leitão [2019223148]

Rodrigo Machado [2019218299]

Rui Costa [2019224237]

In [32]:
# Notebook setup
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

from report import *

%matplotlib inline
%config InlineBackend.figure_format = 'svg'

plt.rcParams['figure.figsize'] = [5, 5]

barn = np.array(Image.open("imagens/barn_mountains.bmp"))
peppers = np.array(Image.open("imagens/peppers.bmp"))
logo = np.array(Image.open("imagens/logo.bmp"))

1. Compressão JPEG usando GIMP¶

1.1. barn_mountains.bmp¶

In [36]:
path = "ex1/barn_mountains"
tmp = np.array(Image.open(f"{path}/high.jpg"))
plt.title("barn_mountains - High (qf=75)")
viewImage(tmp)
2022-03-24T22:01:59.030009 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [37]:
tmp = np.array(Image.open(f"{path}/medium.jpg"))
plt.title("barn_mountains - Medium (qf=50)")
viewImage(tmp)
2022-03-24T22:02:22.016719 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [38]:
tmp = np.array(Image.open(f"{path}/low.jpg"))
plt.title("barn_mountains - Low (qf=25)")
viewImage(tmp)
2022-03-24T22:02:50.203683 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

1.2. peppers.bmp¶

In [39]:
path = "ex1/peppers"
tmp = np.array(Image.open(f"{path}/high.jpg"))
plt.title("peppers - High (qf=75)")
viewImage(tmp)
2022-03-24T22:04:01.810356 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [40]:
tmp = np.array(Image.open(f"{path}/medium.jpg"))
plt.title("peppers - Medium (qf=50)")
viewImage(tmp)
2022-03-24T22:04:13.275538 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [41]:
tmp = np.array(Image.open(f"{path}/low.jpg"))
plt.title("peppers - Low (qf=25)")
viewImage(tmp)
2022-03-24T22:04:23.552915 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

1.3. logo.bmp¶

In [42]:
path = "ex1/logo"
tmp = np.array(Image.open(f"{path}/high.jpg"))
plt.title("logo - High (qf=75)")
viewImage(tmp)
2022-03-24T22:04:55.800651 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [43]:
tmp = np.array(Image.open(f"{path}/medium.jpg"))
plt.title("logo - Medium (qf=50)")
viewImage(tmp)
2022-03-24T22:05:06.475671 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [44]:
tmp = np.array(Image.open(f"{path}/low.jpg"))
plt.title("logo - Low (qf=25)")
viewImage(tmp)
2022-03-24T22:05:14.446895 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

2. Comparação de Y com RGB, e com Cb e Cr¶

In [31]:
# Matplotlib figure sizing
plt.rcParams['figure.figsize'] = [9, 9]

Notas:

  • No modelo de cor RGB não existe uma separação entre a luminância da cor. A variação da luminância de um pixel é partilhada nos 3 canais, pelo que existe uma redundância a qual pode ser aproveitada para obter um maior potencial de compressão.
  • O canal Y resulta da separação da luminância dos 3 canais RGB, e sozinho cria uma imagem acromática da imagem original.
  • O canal Y favorece os canais de forma desigual, pois o olho humano é mais sensível a verde e a vermelho do que a azul
    • $Y \approx 0.3R + 0.6G + 0.1B$
  • Os canais Cb e Cr são canais cromáticos, e representam a diferença dos canais azul e vermelho relativamente à luminância.

TODO Proof-read O modelo RBG é um modelo de cor que tenta simular os cones presentes no olho, criando cores com detalhes fáceis de distinguir pelo olho humano em cada canal. No entanto, esses canais apresentam uma elevada redundância ao conterem todos informação de cor e luminância. Assim, o modelo YCbCR permite uma maior eficiência na compressão ao separar o sinal num componente de lumen, $Y$, e em dois de cor, $Cb$ e $Cr$. Assim, como o sistema visual humano é mais sensível a tonalidades de verde e vermelho, é mais predominante no canal $Y$ uma presença de verde. Os canais de crominância Cb e Cr apresentam cada um a variação de azul e vermelho respetivamente relativo ao lumen.

In [2]:
colormodels(barn)
2022-03-24T21:43:25.924145 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
2022-03-24T21:43:26.032686 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

3. Downsampling e os seus efeitos sobre a imagem¶

Notas:

  • O olho humano é mais sensível à informação de luminância, pelo que faz sentido comprimir destrutivamente as componentes cromáticas, mas não o canal Y.
  • O JPEG apresenta várias rácios de downsampling, entre os quais 4:2:2 e 4:2:0.
  • O rácio 4:2:2 reduz a resolução horizontal em ambos os canais Cb e Cr para metade.
  • O rácio 4:2:0 reduz a resolução horizontal e vertical em ambos os canais Cb e Cr para metade.
  • Intuitivamente, 4:2:0 resulta numa maior taxa de compressão ao custo de uma maior destrutividade da imagem.

4. Transformada de Cosseno Discreta (DCT)¶

4.1. DCT em canais inteiros¶

In [3]:
DCT(barn, ratio=(4,2,0))
2022-03-24T21:43:26.214687 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

TODO Discuta os resultados obtidos em termos de potencial de compressão

4.2. DCT em blocos 8x8¶

In [4]:
DCT(barn, ratio=(4,2,0), block=8)
2022-03-24T21:43:26.428683 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

Compare os resultados obtidos com os resultados de 7.1.2 e discuta-os em termos de potencial de compressão.

4.3. DCT em blocos 64x64¶

In [5]:
DCT(barn, ratio=(4,2,0), block=64)
2022-03-24T21:43:26.641781 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

TODO Compare com os resultados anteriores e tire conclusões.

5. Quantização¶

5.1. Fatores de qualidade e potencial de compressão¶

Fator de qualidade: 100

In [6]:
quantization(barn, qf=100)
2022-03-24T21:43:26.848721 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

Fator de qualidade: 75

In [7]:
quantization(barn, qf=75)
2022-03-24T21:43:27.143723 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

Fator de qualidade: 50

In [8]:
quantization(barn, qf=50)
2022-03-24T21:43:27.326721 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

Fator de qualidade: 25

In [9]:
quantization(barn, qf=25)
2022-03-24T21:43:27.531727 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

Fator de qualidade: 10

In [10]:
quantization(barn, qf=10)
2022-03-24T21:43:27.701741 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

TODO Comparação dos diferentes resultados e discussão da potencialidade de compressão

5.2. Diferenças entre a DCT e DCT quantizada¶

TODO Compare os resultados obtidos com os resultados da alínea 7 e tire conclusões.

6. Codificação DPCM¶

In [11]:
DPCM(barn, ratio=(4,2,0), qf=75)
2022-03-24T21:43:27.904758 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
2022-03-24T21:43:27.992754 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

TODO Analise os resultados e tire conclusões.

7. Codificação e descodificação end-to-end¶

7.1. barn_mountains.bmp¶

In [12]:
verboseMetrics(barn, qf=100, ratio=(4,2,0))
MSE: 20.550
RMSE: 4.533
SNR: 34.058 dB
PSNR: 35.003 dB
2022-03-24T21:43:28.429787 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [13]:
verboseMetrics(barn, qf=75, ratio=(4,2,0))
MSE: 171.586
RMSE: 13.099
SNR: 24.841 dB
PSNR: 25.786 dB
2022-03-24T21:43:28.761898 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [14]:
verboseMetrics(barn, qf=50, ratio=(4,2,0))
MSE: 282.302
RMSE: 16.802
SNR: 22.679 dB
PSNR: 23.624 dB
2022-03-24T21:43:29.116896 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [15]:
verboseMetrics(barn, qf=25, ratio=(4,2,0))
MSE: 422.080
RMSE: 20.545
SNR: 20.932 dB
PSNR: 21.877 dB
2022-03-24T21:43:29.503959 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [16]:
verboseMetrics(barn, qf=10, ratio=(4,2,0))
MSE: 740.352
RMSE: 27.209
SNR: 18.492 dB
PSNR: 19.436 dB
2022-03-24T21:43:29.861954 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

7.2. peppers.bmp¶

In [17]:
verboseMetrics(peppers, qf=100, ratio=(4,2,0))
MSE: 12.649
RMSE: 3.557
SNR: 33.905 dB
PSNR: 37.110 dB
2022-03-24T21:43:30.327968 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [18]:
verboseMetrics(peppers, qf=75, ratio=(4,2,0))
MSE: 70.840
RMSE: 8.417
SNR: 26.423 dB
PSNR: 29.628 dB
2022-03-24T21:43:30.831999 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [19]:
verboseMetrics(peppers, qf=50, ratio=(4,2,0))
MSE: 106.063
RMSE: 10.299
SNR: 24.670 dB
PSNR: 27.875 dB
2022-03-24T21:43:31.318509 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [20]:
verboseMetrics(peppers, qf=25, ratio=(4,2,0))
MSE: 162.495
RMSE: 12.747
SNR: 22.818 dB
PSNR: 26.022 dB
2022-03-24T21:43:31.795508 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [21]:
verboseMetrics(peppers, qf=10, ratio=(4,2,0))
MSE: 341.954
RMSE: 18.492
SNR: 19.586 dB
PSNR: 22.791 dB
2022-03-24T21:43:32.232557 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/

7.3. logo.bmp¶

In [22]:
verboseMetrics(logo, qf=100, ratio=(4,2,0))
MSE: 9.283
RMSE: 3.047
SNR: 41.655 dB
PSNR: 38.454 dB
2022-03-24T21:43:32.603574 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [23]:
verboseMetrics(logo, qf=75, ratio=(4,2,0))
MSE: 33.079
RMSE: 5.751
SNR: 36.137 dB
PSNR: 32.935 dB
2022-03-24T21:43:33.087578 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [24]:
verboseMetrics(logo, qf=50, ratio=(4,2,0))
MSE: 55.404
RMSE: 7.443
SNR: 33.897 dB
PSNR: 30.695 dB
2022-03-24T21:43:33.386600 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [25]:
verboseMetrics(logo, qf=25, ratio=(4,2,0))
MSE: 84.155
RMSE: 9.174
SNR: 32.081 dB
PSNR: 28.880 dB
2022-03-24T21:43:33.699607 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/
In [26]:
verboseMetrics(logo, qf=10, ratio=(4,2,0))
MSE: 182.662
RMSE: 13.515
SNR: 28.716 dB
PSNR: 25.514 dB
2022-03-24T21:43:34.007641 image/svg+xml Matplotlib v3.5.1, https://matplotlib.org/